using Microsoft.SqlServer.Management.Sdk.Sfc;
using System;
using System.Globalization;
using System.Runtime.CompilerServices;

namespace Microsoft.SqlServer.Management.SqlManagerUI.Scripting
{
	internal class ScriptWriter : IDisposable
	{
		private string batchSeparator;

		private bool includeContext;

		private TextWriterProvider writerProvider;

		private string currentContext = string.Empty;

		private Urn itemUrn;

        public event EventHandler<ScriptingProgressEventArgs> WritingObject;
        //{
        //    [MethodImpl(MethodImplOptions.Synchronized)]
        //    add
        //    {
        //        this.WritingObject = (EventHandler<ScriptingProgressEventArgs>)Delegate.Combine(this.WritingObject, value);
        //    }
        //    [MethodImpl(MethodImplOptions.Synchronized)]
        //    remove
        //    {
        //        this.WritingObject = (EventHandler<ScriptingProgressEventArgs>)Delegate.Remove(this.WritingObject, value);
        //    }
        //}

		public ScriptWriter(string batchSeparator, bool includeContext, TextWriterProvider writerProvider)
		{
			if (writerProvider == null)
			{
				throw new ArgumentNullException("writerProvider");
			}
			this.writerProvider = writerProvider;
			this.batchSeparator = ((batchSeparator == null) ? string.Empty : batchSeparator);
			this.includeContext = includeContext;
		}

		public bool IsWritingObjectOfTypeSupported(object obj)
		{
			bool result = false;
			if (this.writerProvider is IObjectsSupported)
			{
				IObjectsSupported objectsSupported = (IObjectsSupported)this.writerProvider;
				result = objectsSupported.IObjectsSupported(obj);
			}
			return result;
		}

		public void WriteObject(object obj)
		{
			if (obj == null)
			{
				throw new InvalidOperationException();
			}
			if (this.IsWritingObjectOfTypeSupported(obj))
			{
				IObjectsSupported objectsSupported = (IObjectsSupported)this.writerProvider;
				objectsSupported.WriteObject(obj);
				return;
			}
			if (obj is string)
			{
				this.Write((string)obj);
				return;
			}
			throw new InvalidOperationException();
		}

		public void InitializeWriterForUrn(Microsoft.SqlServer.Management.SqlManagerUI.ObjectInfo objectInfo, ScriptActions action)
		{
			this.writerProvider.InitializeForUrn(objectInfo.Urn);
			if (this.WritingObject != null && !string.IsNullOrEmpty(objectInfo.Name) && (action == ScriptActions.Create || action == ScriptActions.Drop || action == ScriptActions.Data))
			{
				this.WritingObject(this, new ScriptingProgressEventArgs(objectInfo, action));
			}
			this.itemUrn = objectInfo.Urn;
		}

		public void CloseWriterForUrn()
		{
			this.writerProvider.DisposeForUrn();
			this.itemUrn = null;
		}

		public virtual void Write(string script)
		{
			this.Write(script, true);
		}

		public virtual void Write(string script, bool useBatch)
		{
			if (script == null)
			{
				script = string.Empty;
			}
			this.WriteContext();
			this.writerProvider.WriteLine(script);
			if (useBatch)
			{
				this.WriteBatchSeparator();
			}
		}

		public virtual void WriteComment(string comment)
		{
			if (comment == null || comment.Length == 0)
			{
				return;
			}
			this.WriteContext();
			this.writerProvider.WriteLine(comment);
		}

		private void WriteBatchSeparator()
		{
			if (this.batchSeparator.Length > 0)
			{
				this.writerProvider.WriteLine(this.batchSeparator);
			}
		}

		private void WriteContext()
		{
			if (!this.includeContext)
			{
				return;
			}
			string contextForItem = ScriptWriter.GetContextForItem(this.itemUrn);
			if (contextForItem != this.currentContext)
			{
				this.writerProvider.WriteLine(string.Format(CultureInfo.InvariantCulture, "USE [{0}]", new object[]
				{
					ReflectionUtilities.EscapeString(contextForItem, ']')
				}));
				this.WriteBatchSeparator();
				this.currentContext = contextForItem;
			}
		}

		private static string GetContextForItem(Urn item)
		{
			if (item.Type == "Database")
			{
				return "master";
			}
			do
			{
				item = item.Parent;
			}
			while (item != null && item.Type != "Database");
			if (item != null)
			{
				return item.GetAttribute("Name");
			}
			return "master";
		}

		public void Dispose()
		{
			if (this.writerProvider != null)
			{
				this.writerProvider.Dispose();
			}
		}
	}
}
